package com.cf.game.stage;

import com.cf.Event;
import com.cf.core.event.EndEvent;
import com.cf.core.event.HeartbeatEvent;
import com.cf.core.event.TicketEvent;
import com.cf.core.player.Player;
import com.cf.core.spirit.Spiriter;
import com.cf.core.stage.HeartBeatStage;
import com.cf.game.GameContext;
import com.cf.game.message.GameResultResponse;
import com.cf.game.message.GameStartResponse;
import com.cf.game.message.PunishNotifyResponse;
import com.cf.game.message.PunishResponse;
import com.cf.game.message.vo.UserInfo;
import com.cf.game.service.constants.EnumCoinReocrdType;
import com.cf.game.service.service.UserInfoService;
import com.cf.game.service.util.BeanFactoryUtil;
import com.cf.game.stage.event.ChangeStatueEvent;
import com.cf.game.stage.event.MaybePunishEvent;
import com.cf.game.stage.event.PunishEvent;
import com.cf.game.stage.npc.EnumStudentStatue;
import com.cf.game.stage.npc.President;
import com.cf.game.stage.npc.RobotStudent;
import com.cf.game.stage.npc.Student;
import com.cf.serialize.Response;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * game-server-GameStage
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info
 * @since 2018/5/7 下午 03:00
 */
@Slf4j
public class ClassRoom extends HeartBeatStage {


    private Map<Integer, Student> students = new HashMap<>();

    private List<Spiriter> roomSpiriter = new ArrayList();


    /**
     * 房间的初始状态是COMMON
     */
    private String statue = EnumStudentStatue.COMMON.getStatue();

    public ClassRoom(int stageTime, Player p1, Player p2) {
        super(1, stageTime, UUID.randomUUID().toString());
        List<Player> players = createPlayer(p1, p2);
        createNpc();
        BeanFactoryUtil.getBean(ClassRoomManager.class).addRoom(this, players);
    }

    private List<Player> createPlayer(Player p1, Player p2) {
        Student s2;
        if (p2 == null) {
            log.info("二号玩家是个机器人！。。。房间号是【{}】", this.getStageNum());
            p2 = new RobotPlayer();
            s2 = new RobotStudent(this, p1);
        } else {
            s2 = new Student(this, p2, p1);
        }

        Student s1 = new Student(this, p1, p2);
        students.put(p1.getId(), s1);
        students.put(p2.getId(), s2);
        roomSpiriter.addAll(Arrays.asList(s1, s2));
        this.registerEventHandler(s1);
        this.registerEventHandler(s2);

        UserInfo p1UserInfo = new UserInfo(p1.getId(), p1.getName(), p1.getHead(), p1.getLocation());
        UserInfo p2UserInfo = new UserInfo(p2.getId(), p2.getName(), p2.getHead(), p2.getLocation());

        p1.sendMessage(new GameStartResponse(getStageNum(), p1UserInfo, p2UserInfo, this.getStageLeftTime(), this.getStageTime()));
        p2.sendMessage(new GameStartResponse(getStageNum(), p2UserInfo, p1UserInfo, this.getStageLeftTime(), this.getStageTime()));
        return Arrays.asList(p1, p2);
    }

    private void createNpc() {
        President president = new President(this);
        roomSpiriter.addAll(Arrays.asList(president));
        this.registerEventHandler(president);
    }

    @Override
    protected void handleEvent(Event event) {
        if (event instanceof HeartbeatEvent)
            return;

        if (event instanceof EndEvent) {
            //处理游戏结果
            sendGameReward();
            //游戏结束
            this.end();
            return;
        } else if (event instanceof ChangeStatueEvent) {
            //更改状态的消息不需要广播
            this.statue = ((ChangeStatueEvent) event).getStatue();
            return;
        } else if (event instanceof PunishEvent) {
            //处理惩罚消息
            handPunishEvent((PunishEvent) event);
        } else if (event instanceof MaybePunishEvent) {
            //处理maybe惩罚消息
            handleMaybePunish();
        }

    }

    private void handleMaybePunish() {
        userBroadcast(new PunishResponse(0));
    }

    private void handPunishEvent(PunishEvent event) {
        log.info("开始处理房间【{}】的惩罚消息", this.getStageNum());
        Student[] students = this.students.values().toArray(new Student[]{});
        Student p1 = students[0];
        Student p2 = students[1];
        boolean p1Punished = p1.handlePunish(event);
        boolean p2Punished = p2.handlePunish(event);

        if (p1Punished || p2Punished) {
            this.statue = EnumStudentStatue.PUNISH.getStatue();
            userBroadcast(new PunishResponse(1));
            log.info("有人收到惩罚【{}】【{}】", p1Punished, p2Punished);
            /**
             *发送惩罚通知
             */
            if (p1Punished && p2Punished) {
                //两个都收到惩罚
                PunishNotifyResponse notifyResponse = new PunishNotifyResponse(true, true);
                userBroadcast(notifyResponse);
                return;
            }
            if (p1Punished && !p2Punished) {
                p1.getSelf().sendMessage(new PunishNotifyResponse(true, false));
                p2.getSelf().sendMessage(new PunishNotifyResponse(false, false));
                return;
            }
            if (!p1Punished && p2Punished) {
                p1.getSelf().sendMessage(new PunishNotifyResponse(false, false));
                p2.getSelf().sendMessage(new PunishNotifyResponse(true, false));
                return;
            }
        }
    }

    /**
     * 给用户广播消息
     *
     * @param response
     */
    private void userBroadcast(Response response) {
        this.students.values().forEach(student -> {
            student.getSelf().sendMessage(response);
        });
    }

    private void sendGameReward() {
        Student maxScoreStudent = getMaxScoreStudent();
        Integer money = BeanFactoryUtil.getBean(GameContext.class).getH5Game().getMoney();
        BeanFactoryUtil.getBean(UserInfoService.class).addUserCoinAmountAndSendMsg(maxScoreStudent.getId(), money * 2, EnumCoinReocrdType.XUE_XIAO_BA_WANG.getType(), "学校霸王奖励", "学校霸王获胜奖励", "您学校霸王获胜奖励以到账，请及时查收！");
        sendGameResultMessage(maxScoreStudent, students.values());
    }

    /**
     * 发送游戏结果数据
     *
     * @param maxScoreStudent
     * @param values
     */
    private void sendGameResultMessage(Student maxScoreStudent, Collection<Student> values) {
        values.forEach(student -> {
            if (student.equals(maxScoreStudent)) {
                Player self = student.getSelf();
                UserInfo userInfo = new UserInfo(self.getId(), self.getName(), self.getHead(), "无");
                GameResultResponse gameResultResponse = new GameResultResponse(userInfo, true);
                student.getSelf().sendMessage(gameResultResponse);
            } else {
                Player self = student.getSelf();
                UserInfo userInfo = new UserInfo(self.getId(), self.getName(), self.getHead(), "无");
                GameResultResponse gameResultResponse = new GameResultResponse(userInfo, false);
                student.getSelf().sendMessage(gameResultResponse);
            }
        });

    }

    private Student getMaxScoreStudent() {
        final Student[] maxScoreStudent = {null};
        students.values().forEach(student -> {
            log.info("用户【{}】，获得分数【{}】", student.getId(), student.getTotalScore());
            if (maxScoreStudent[0] == null) {
                maxScoreStudent[0] = student;
            } else {
                Student ms = maxScoreStudent[0];
                if (ms.getTotalScore() < student.getTotalScore()) {
                    maxScoreStudent[0] = student;
                }
            }
        });
        return maxScoreStudent[0];
    }

    @Override
    protected void handleTicketEvent(TicketEvent event) {
        int leftTime = this.reduceAndGetLeftTime();
        log.info("当前游戏剩余【{}】", leftTime);
        if (leftTime <= 0) {
            this.broadcastEvent(new EndEvent());
        } else {
            HeartbeatEvent heartbeatEvent = new HeartbeatEvent();
            heartbeatEvent.setGameTime(getStageTime());
            heartbeatEvent.setLeftTime(getStageLeftTime());
            this.broadcastEvent(heartbeatEvent);
        }
    }

    @Override
    protected void clean() {
        roomSpiriter.forEach(spiriter -> {
            spiriter.clean();
        });
        List<Player> players = new ArrayList<>();
        students.values().forEach(student -> {
            players.add(student.getSelf());
        });
        BeanFactoryUtil.getBean(ClassRoomManager.class).removeRoom(this.getStageNum(), players);
    }

    public Spiriter getSuitableSpiriter(Integer userToken) {
        return students.get(userToken);
    }


    @Override
    public String getStatue() {
        return statue;
    }
}